package com.netty.websocket;

import com.alibaba.fastjson.JSONObject;
import io.netty.channel.group.ChannelGroup;
import io.netty.channel.group.ChannelGroupFuture;
import io.netty.channel.group.ChannelMatchers;
import io.netty.channel.group.DefaultChannelGroup;
import io.netty.handler.codec.http.websocketx.WebSocketFrame;
import io.netty.util.concurrent.GlobalEventExecutor;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;

public final class GroupManager {
   // private String queue;
    private ConcurrentHashMap<QueueType,BaseChannelGroup> mapGroupManager=new ConcurrentHashMap();//记录所有QueueType的 BaseChannelGroup
    private ConcurrentHashMap<String,String> mapOnlineSockIdUserId=new ConcurrentHashMap();//在线用户列表
    public String recvQueue;
    public ChannelGroup allChannelGroup;//当前队列的 所有 连接端

    public static ConcurrentHashMap<String,GroupManager> mapGroup=new ConcurrentHashMap();//记录所有队列的GroupManager
    public static GroupManager newOrFind(String recvQueue) {
        if(mapGroup==null) mapGroup=new ConcurrentHashMap();
        GroupManager groupManager = mapGroup.get(recvQueue);
        if (groupManager == null) {
            groupManager = new GroupManager();//channelGroupMagager.queue=queue;
            groupManager.recvQueue=recvQueue;
            groupManager.allChannelGroup = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);
            mapGroup.put(recvQueue, groupManager);
        }
        return groupManager;
    }


    public ConcurrentHashMap.KeySetView<QueueType, BaseChannelGroup> keySet() {
        return mapGroupManager.keySet();
    }

    public BaseChannelGroup get(QueueType key) {
        return mapGroupManager.get(key);
    }

    public void add(QueueType queueType,NettySession nettySession) {
        if (queueType == QueueType.PC_ONE || queueType == QueueType.P_ONE || queueType == QueueType.C_ONE){
            //_ONE的都要轮训
            mapGroupManager.put(queueType,ComsumerChannelGroup.newOrFind(this.recvQueue,queueType).add(nettySession));
        }else{
            //都发送
            mapGroupManager.put(queueType,SimpleChannelGroup.newOrFind(this.recvQueue,queueType).add(nettySession));
        }
        mapOnlineSockIdUserId.put(nettySession.getId(),nettySession.getUserd());
        allChannelGroup.add(nettySession.channel());
    }

    public void remove(QueueType queueType,NettySession nettySession) {
        BaseChannelGroup group=mapGroupManager.get(queueType);
        if (group!=null) group.remove(nettySession);

        mapOnlineSockIdUserId.remove(nettySession.getId(),nettySession.getUserd());
        allChannelGroup.add(nettySession.channel());
    }

    /*
        当前队列的所有客户端在allChannelGroup对象中
        给所有客户端 发送 上线 下线通知用这个方法
     */
    public boolean writeAndFlush(NettySession nettySession,WebSocketFrame message){
        ChannelGroupFuture cgf = allChannelGroup.writeAndFlush(message, ChannelMatchers.isNot(nettySession.channel()), false);//发送消息的channel不要收到自己发送的消息
        return cgf.isSuccess();
    }

    public boolean writeAndFlush(QueueType queueType,NettySession nettySession,WebSocketFrame message){
        BaseChannelGroup baseChannelGroup=get(queueType);
        if(baseChannelGroup!=null && baseChannelGroup.size()>0){
            if (queueType==QueueType.PC_MORE) {
                return baseChannelGroup.writeAndFlush2(nettySession, this.recvQueue, message);//给队列的所有人发送消息(含自己)
            }else{
                return baseChannelGroup.writeAndFlush (nettySession, this.recvQueue, message);//给队列的所有人发送消息(不含自己)
            }
        }
        return false;
    }

    public Integer getOnlineSocks() {
        return mapOnlineSockIdUserId.keySet().size();
    }
    public List<JSONObject> getOnlineUsers() {
        List<JSONObject> users=new ArrayList();
        HashMap<String,String> mapUserId_sockIds=new HashMap();
        String userId, sockIds="",sockIdsOld="";//一个用户userId有 多个sockId
        for (String sockId2 : mapOnlineSockIdUserId.keySet()){
            userId=mapOnlineSockIdUserId.get(sockId2);
            if(userId==null || userId.equals("")){
                //userId=sockId2;
                continue;
            }
            sockIdsOld=mapUserId_sockIds.get(userId);
            if(sockIdsOld==null)sockIdsOld="";
            sockIds=sockIdsOld+(sockIdsOld.equals("")?"":",")+sockId2;
            mapUserId_sockIds.put(userId,sockIds);
        }
        for (String userIdCur : mapUserId_sockIds.keySet()){
            sockIds=mapUserId_sockIds.get(userIdCur);
            JSONObject row =new JSONObject(true);
            row.put("userId",userIdCur);
            row.put("sockIds",sockIds);
            users.add(row);
        }
        return users;
    }
}
